import base64, pickle, json
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection
from django.http import JsonResponse

from goods.models import *
from carts import const
from meiduo.utils.response_code import RETCODE


class ShoppingCarView(View):
    """购物车视图"""
    def get(self,request):
        # 显示购物车视图
        user = request.user
        sku_list = list()
        if user.is_authenticated:
            # 判断是否为用户
            conn = get_redis_connection(alias='carts')
            carts_dict_bite = conn.hgetall("carts_%d"%user.id)
            selecteds = conn.smembers("selected_%d"%user.id)
            cart_dict = {}
            # 获取hash对象字典
            for sku_id in carts_dict_bite:
                # 获取sku模型对象
                cart_dict[int(sku_id)]={
                    "count":int(carts_dict_bite[sku_id]),
                    "selected": sku_id in selecteds,   # 在集合中返回ture   否则返回 false
                }
        else:
            # 游客身份登录
            cart_dict_str = request.COOKIES.get("carts")

            if not cart_dict_str:
                # cookie 中无数据提前响应
                return render(request,"cart.html")
            try:
                cart_dict_bite = cart_dict_str.encode()
                cart_dict_bite_p = base64.b64decode(cart_dict_bite)
                cart_dict = pickle.loads(cart_dict_bite_p)
                # cart_dict = pickle.loads(base64.b16decode(cart_dict_str.encode()))
            except:
                return render(request,"404.html")

        cart_skus = list()
        sku_qs = SKU.objects.filter(id__in=cart_dict.keys())
        # 获取sku查询集

        for sku in sku_qs:
            # 数据格式化
            cart_skus.append({
                "id":sku.id,
                "selected":str(cart_dict[sku.id]["selected"]),
                "default_image_url":sku.default_image.url,
                "name":sku.name,
                "price":str(sku.price),
                "count":int(cart_dict[sku.id]["count"]),
                "amount":str(cart_dict[sku.id]["count"] * sku.price)
            })

        context = {
            "cart_skus":cart_skus
        }
        return render(request,"cart.html",context)

    def post(self,request):
        # 添加购物车
        # 获取数据
        data_dict = json.loads(request.body.decode())
        sku_id = data_dict.get("sku_id")
        count = data_dict.get("count")
        # 校验数据
        if not all([sku_id,count]):
            return render(request,"404.html")
        try:
            SKU.objects.get(id=sku_id,is_launched=True)
        except SKU.DoesNotExist:
            return render(request,"404.html")
        # 逻辑处理
        user = request.user
        if user.is_authenticated:
            # 用户  购物车数据存入redis 4#库中
            conn = get_redis_connection(alias='carts')
            pl = conn.pipeline()
            pl.hincrby("carts_%d"%user.id,str(sku_id),amount=count)
            pl.sadd("selected_%d"%user.id,str(sku_id))
            pl.expire("carts_%d"%user.id,const.user_carts_save_time)
            pl.expire("selected_%d"%user.id,const.user_carts_save_time)
            pl.execute()

            return JsonResponse({"code":RETCODE.OK,"errmsg":"ok"})
        else:
            # 游客  购物车数据保存在cookie中
            cart_dict = request.COOKIES.get("carts")
            # 尝试获取cookie中有无信息
            if cart_dict:
                # cookie中有信息
                try:
                    cart_dict_bite = cart_dict.encode()
                    cart_dict_bite_p = base64.b64decode(cart_dict_bite)
                    cart_dict = pickle.loads(cart_dict_bite_p)
                except:
                    return render(request,"404.html")
            else:
                cart_dict = {}

            if sku_id in cart_dict.keys():
                cart_dict[sku_id]["count"] += count
            else:
                cart_dict[sku_id]={"count":count,"selected":True}

            cart_dict = base64.b64encode(pickle.dumps(cart_dict)).decode()
            # 响应
            response = JsonResponse({"code":RETCODE.OK,"errmsg":"ok"})
            response.set_cookie("carts",cart_dict,const.visitor_carts_save_time)
            return response

    def put(self,request):
        # 接收数据
        recieve_dict = json.loads(request.body.decode())
        sku_id = recieve_dict.get("sku_id")
        count = recieve_dict.get("count")
        selected = recieve_dict.get("selected")

        # 验证数据
        if not all([sku_id,count]):
            return JsonResponse({"code":RETCODE.DBERR,"errmsg":"数据错误"})
        try:
            sku = SKU.objects.get(id=sku_id,is_launched=True)
        except SKU.DoesNotExist:
            return render(request, "404.html")
        if not isinstance(selected,bool):
            return render(request, "404.html")
        try:
            count = int(count)
        except:
            return render(request, "404.html")

        cart_sku = {
            "id": sku.id,
            "selected": selected,
            "default_image_url": sku.default_image.url,
            "name": sku.name,
            "price": str(sku.price),
            "count": int(count),
            "amount": str(count * sku.price),
        }
        response = JsonResponse({"code":RETCODE.OK,"errmsg":"ok","cart_sku":cart_sku})
        # 逻辑处理
        user = request.user
        if user.is_authenticated:
            # 用户身份
            conn = get_redis_connection(alias='carts')
            pl = conn.pipeline()
            # 更改redis数据库数据
            pl.hset("carts_%d"%user.id,sku_id,count)
            pl.srem("selected_%d"%user.id,sku_id)
            if selected:
                pl.sadd("selected_%d"%user.id,sku_id)
            pl.expire("selected_%d"%user.id,const.user_carts_save_time)
            pl.expire("carts_%d"%user.id,const.user_carts_save_time)
            pl.execute()

        else:
            # 游客身份
            carts_dict_str = request.COOKIES.get("carts")
            if not carts_dict_str:
                return render(request,"404.html")
            try:
                cart_dict = pickle.loads(base64.b64decode(carts_dict_str.encode()))
            except:
                return render(request,"404.html")
            # 更改数据
            cart_dict[sku_id]["count"] = count
            cart_dict[sku_id]["selected"] = selected

            # 格式化数据
            carts_dict_str = base64.b64encode(pickle.dumps(cart_dict)).decode()
            response.set_cookie("carts",carts_dict_str,const.visitor_carts_save_time)
        # 响应
        return response

    def delete(self,request):
        """删除购物车"""
        # 接收数据
        sku_id = json.loads(request.body.decode()).get("sku_id")

        # 校验数据
        try:
            sku = SKU.objects.get(id=sku_id,is_launched=True)
        except SKU.DoesNotExist:
            return render(request,"404.html")

        # 逻辑处理
        user = request.user
        response = JsonResponse({"code":RETCODE.OK,"errmsg":"ok"})
        if user.is_authenticated:
            # 用户
            conn = get_redis_connection(alias='carts')
            carts_dict = conn.hgetall("carts_%d"%user.id)
            if str(sku_id).encode() not in carts_dict.keys():
                # 传入数据有误
                return render(request,"404.html")
            pl = conn.pipeline()
            pl.hdel("carts_%d"%user.id,sku_id)   # 删除建值对
            pl.srem("selected_%d"%user.id,sku_id)
            pl.execute()

        else:
            # 游客
            carts_dict_str = request.COOKIES.get("carts")
            if not carts_dict_str:
                return render(request,"404.html")
            try:
                carts_dict = pickle.loads(base64.b64decode(carts_dict_str.encode()))
            except:
                return render(request,"404.html")
            if sku_id not in carts_dict.keys():
                # 数据有误
                return render(request,"404.html")

            # 删除记录
            del carts_dict[sku_id]
            if not carts_dict:
                response.delete_cookie("carts")
                return response

            carts_dict_str = base64.b64encode(pickle.dumps(carts_dict)).decode()
            response.set_cookie("carts",carts_dict_str,const.visitor_carts_save_time)

        # 响应
        return response

"""
redis中用户购物车数据结构
hash    carts_id: {sku_id:count,sku_id_2:count}
setid   selected_id: {sku_id}  表示sku_id商品是否勾选
"""
"""
游客cookie保存数据结构
carts:  {
ku_id:{count:"",selected:""}
}
"""


class ShoppingCartSelectAll(View):
    """购物车全选视图"""
    def put(self,request):
        # 接受数据
        selected = json.loads(request.body.decode()).get("selected")
        if (selected is None) or (not isinstance(selected, bool)):
            return JsonResponse({"code":RETCODE.PARAMERR,"errmsg":"参数错误"})

        user = request.user
        if user.is_authenticated:
            # 用户
            conn = get_redis_connection(alias='carts')
            carts_dict_bite = conn.hgetall("carts_%d"%user.id)
            pl = conn.pipeline()
            if not carts_dict_bite:
                return JsonResponse({"code":RETCODE.OK,"errmsg":"ok"})
            if selected:
                # 全选
                for sku_id in carts_dict_bite:
                    pl.sadd("selected_%d"%user.id,sku_id)
            else:
                pl.delete("selected_%d"%user.id)
            pl.execute()

            return JsonResponse({"code":RETCODE.OK,"errmsg":"ok"})
        else:
            # 游客
            carts_dict_str = request.COOKIES.get("carts")
            if not carts_dict_str:
                return JsonResponse({"code":RETCODE.OK,"errmsg":"无数据"})

            carts_dict = pickle.loads(base64.b64decode(carts_dict_str.encode()))
            # 修改数据
            for sku_dict in carts_dict.values():
                sku_dict["selected"] = selected

            carts_dict_str = base64.b64encode(pickle.dumps(carts_dict)).decode()
            response = JsonResponse({"code":RETCODE.OK,"errmsg":"ok"})

            response.set_cookie("carts",carts_dict_str,const.visitor_carts_save_time)

            return response


class ShoppingCarSimpleView(View):
    """购物车简易视图"""
    def get(self,request):
        "获取简易购物车视图"

        user = request.user
        carts = list()
        if user.is_authenticated:
        # 用户
            conn = get_redis_connection(alias='carts')
            cart_dict_bite = conn.hgetall("carts_%d"%user.id)
            if not cart_dict_bite:
                return JsonResponse({"code":RETCODE.NODATAERR,"errmsg":"无数据"})

            sku_qs = SKU.objects.filter(id__in=cart_dict_bite.keys(), is_launched=True)

            for sku in sku_qs:
                carts.append({
                    "id": sku.id,
                    "name": sku.name,
                    "default_image_url": sku.default_image.url,
                    "count": int(cart_dict_bite[str(sku.id).encode()])
                })

        else:
        # 游客
            carts_dict_str = request.COOKIES.get("carts")
            if not carts_dict_str:
                return JsonResponse({"code":RETCODE.NODATAERR,"errmsg":"无数据"})
            try:
                carts_dict = pickle.loads(base64.b64decode(carts_dict_str.encode()))
            except:
                return render(request,"404.html")
            sku_qs = SKU.objects.filter(id__in=carts_dict.keys(),is_launched=True)

            for sku in sku_qs:
                carts.append({
                    "id": sku.id,
                    "name": sku.name,
                    "default_image_url": sku.default_image.url,
                    "count": carts_dict[sku.id]["count"]
                })
        return JsonResponse({"code":RETCODE.OK,"errmsg":"ok","cart_skus":carts})


